package com.Cychat.doctor.service.impl;

import com.Cychat.commons.entity.pojo.Appointment;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.Cychat.commons.entity.pojo.Drug;
import com.Cychat.commons.entity.pojo.TreatmentRecord;
import com.Cychat.commons.entity.vo.AppointmentDetailVo;
import com.Cychat.commons.entity.vo.TreatmentVo;
import com.Cychat.doctor.mapper.TreatmentRecordMapper;
import com.Cychat.doctor.service.TreatmentRecordService;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
public class TreatmentRecordServiceImpl extends ServiceImpl<TreatmentRecordMapper, TreatmentRecord> implements TreatmentRecordService {

    @Autowired
    private ObjectMapper objectMapper;

    /**
     * 分页查询诊疗VO（关联预约、宠物、主人、药品信息）
     */
    @Override
    public IPage<TreatmentVo> getTreatmentVoPage(Page<TreatmentRecord> page, Integer doctorId, Integer appointmentId, String keyword) {
        // 1. 构造查询条件（过滤医生ID、预约ID、关键词）
        LambdaQueryWrapper<TreatmentRecord> queryWrapper = new LambdaQueryWrapper<TreatmentRecord>()
                .eq(doctorId != null, TreatmentRecord::getAppointmentId, appointmentId) // 预约ID筛选
                .like(StringUtils.hasText(keyword), TreatmentRecord::getDiagnosis, keyword) // 关键词匹配诊断结果
                // 过滤当前医生的诊疗记录（通过预约表的doctor_id关联）
                .eq(doctorId != null, tr -> tr.getAppointmentId() != null, doctorId); // 这里实际是通过预约表doctor_id过滤，SQL已关联

        // 2. 分页查询诊疗记录
        IPage<TreatmentRecord> treatmentPage = baseMapper.selectTreatmentPage(page, queryWrapper);

        // 3. 转换为TreatmentVo（关联所有信息）
        return treatmentPage.convert(this::convertToTreatmentVo);
    }

    /**
     * 根据ID查询诊疗VO详情
     */
    @Override
    public TreatmentVo getTreatmentVoById(Integer treatmentId) {
        TreatmentRecord treatment = baseMapper.selectTreatmentById(treatmentId);
        return treatment != null ? convertToTreatmentVo(treatment) : null;
    }

    /**
     * 新增诊疗记录（校验drugIds格式）
     */
    @Override
    public boolean saveTreatment(TreatmentRecord treatment) {
        // 1. 校验药品ID格式（必须是JSON数组字符串）
        if (!validateDrugIds(treatment.getDrugIds())) {
            throw new IllegalArgumentException("药品ID格式错误，需为JSON数组（例：[1,2,3]）");
        }
        // 2. 补充创建时间
        if (treatment.getCreateDate() == null) {
            treatment.setCreateDate(new Date());
        }
        // 3. 保存
        return save(treatment);
    }

    /**
     * 编辑诊疗记录
     */
    @Override
    public boolean updateTreatment(TreatmentRecord treatment) {
        // 1. 校验药品ID格式
        if (!validateDrugIds(treatment.getDrugIds())) {
            throw new IllegalArgumentException("药品ID格式错误，需为JSON数组（例：[1,2,3]）");
        }
        // 2. 校验记录是否存在
        if (!this.lambdaQuery().eq(TreatmentRecord::getTreatmentId, treatment.getTreatmentId()).exists()) {
            throw new IllegalArgumentException("诊疗记录不存在");
        }
        // 3. 更新
        return updateById(treatment);
    }

    /**
     * 核心转换：TreatmentRecord -> TreatmentVo
     */
    private TreatmentVo convertToTreatmentVo(TreatmentRecord treatment) {
        TreatmentVo vo = new TreatmentVo();
        BeanUtils.copyProperties(treatment, vo);

        try {
            // 1. 关联预约详情（含宠物、主人信息）
            AppointmentDetailVo appointmentDetail = baseMapper.selectAppointmentDetail(treatment.getAppointmentId());
            if (appointmentDetail != null) {
                // 这里假设你的Appointment实体有对应的setter方法，直接赋值
                // 若Appointment实体字段与AppointmentDetailVo不一致，需手动映射
                vo.setAppointment(appointmentDetail);
            }

            // 2. 解析药品ID，查询药品列表
            List<Integer> drugIds = parseDrugIds(treatment.getDrugIds());
            List<Drug> drugs = baseMapper.selectDrugListByIds(drugIds);
            List<TreatmentVo.DrugVo> voDrugs = drugs.stream().map(drug -> {
                TreatmentVo.DrugVo voDrug = new TreatmentVo.DrugVo();
                BeanUtils.copyProperties(drug, voDrug);
                return voDrug;
            }).collect(Collectors.toList());
            vo.setDrugs(voDrugs);


        } catch (Exception e) {
            log.error("转换诊疗VO失败", e);
            throw new RuntimeException("查询关联数据失败");
        }

        return vo;
    }

    /**
     * 解析drugIds（Object类型 -> List<Integer>）
     */
    private List<Integer> parseDrugIds(Object drugIdsObj) {
        if (drugIdsObj == null) {
            return new ArrayList<>();
        }
        // 若前端传JSON字符串，直接解析；若已转换为List，直接返回
        if (drugIdsObj instanceof String) {
            try {
                return objectMapper.readValue((String) drugIdsObj, new TypeReference<List<Integer>>() {});
            } catch (Exception e) {
                throw new RuntimeException("解析药品ID失败");
            }
        } else if (drugIdsObj instanceof List) {
            return (List<Integer>) drugIdsObj;
        } else {
            throw new RuntimeException("药品ID格式不支持");
        }
    }

    /**
     * 校验drugIds格式
     */
    private boolean validateDrugIds(Object drugIdsObj) {
        if (drugIdsObj == null) {
            return false;
        }
        try {
            parseDrugIds(drugIdsObj);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    // 实现方法：查询医生的预约列表（关联宠物、主人信息）
    public IPage<AppointmentDetailVo> getDoctorAppointmentPage(Page<Appointment> page, Integer doctorId) {
        // 创建查询条件
        QueryWrapper<Appointment> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByDesc("appointment_date");

        // 1. 分页查询该医生的预约记录（使用自定义方法）
        IPage<Appointment> appointmentPage = baseMapper.selectPage(page, doctorId, queryWrapper);

        // 2. 转换为AppointmentDetailVo（关联宠物、主人信息）
        return appointmentPage.convert(appointment ->
                baseMapper.selectAppointmentDetail(appointment.getAppointmentId())
        );
    }

    /**
     * 查询当前医生的所有诊疗记录（处理连表数据，聚合药品列表）
     */
    @Override
    public List<TreatmentVo> getDoctorTreatmentList(Integer doctorId) {
        Assert.notNull(doctorId, "医生ID不能为空");

        List<TreatmentVo> rawList = baseMapper.selectDoctorTreatmentList(doctorId);
        if (rawList.isEmpty()) {
            return new ArrayList<>();
        }

        // 遍历解析药品ID，查询药品
        for (TreatmentVo vo : rawList) {
            try {
                String drugIdsJson = vo.getDrugIds();
                List<Integer> drugIds = new ArrayList<>();

                // 关键修复：用 FastJSON 解析，兼容更多格式
                if (StringUtils.hasText(drugIdsJson)) {
                    // 直接解析 JSON 字符串为 List<Integer>
                    drugIds = JSON.parseArray(drugIdsJson, Integer.class);
                    log.info("解析药品ID成功，诊疗ID：{}，drugIds：{}", vo.getTreatmentId(), drugIds);
                } else {
                    log.warn("诊疗ID：{} 无药品ID", vo.getTreatmentId());
                    vo.setDrugs(new ArrayList<>());
                    continue;
                }

                // 检查解析结果是否为空
                if (drugIds.isEmpty()) {
                    log.warn("诊疗ID：{} 药品ID为空", vo.getTreatmentId());
                    vo.setDrugs(new ArrayList<>());
                    continue;
                }

                // 查询药品信息（关键：打印日志确认是否查询到药品）
                List<com.Cychat.commons.entity.pojo.Drug> dbDrugs = baseMapper.selectDrugListByIds(drugIds);
                log.info("诊疗ID：{} 查询到药品数量：{}", vo.getTreatmentId(), dbDrugs.size());

                // 转换为 DrugVo（打印日志确认字段映射）
                List<TreatmentVo.DrugVo> drugVos = dbDrugs.stream().map(dbDrug -> {
                    TreatmentVo.DrugVo drugVo = new TreatmentVo.DrugVo();
                    drugVo.setDrugId(dbDrug.getDrugId());
                    drugVo.setName(dbDrug.getName());
                    drugVo.setSpecification(dbDrug.getSpecification());
                    drugVo.setUsages(dbDrug.getUsages()); // 确保 dbDrug 有 getUsages() 方法
                    drugVo.setContraindication(dbDrug.getContraindication());
                    drugVo.setPrice(dbDrug.getPrice() != null ? dbDrug.getPrice().doubleValue() : 0.0); // 处理 null
                    log.info("药品转换：{} -> {}", dbDrug.getName(), drugVo.getName());
                    return drugVo;
                }).collect(Collectors.toList());

                vo.setDrugs(drugVos);

            } catch (Exception e) {
                log.error("诊疗ID：{} 解析药品失败", vo.getTreatmentId(), e); // 打印详细异常
                vo.setDrugs(new ArrayList<>());
            }
        }

        return rawList;
    }

    /**
     * 查询诊疗详情（处理药品列表聚合）
     */
    @Override
    public TreatmentVo getDoctorTreatmentDetail(Integer treatmentId, Integer doctorId) {
        // 校验参数
        Assert.notNull(treatmentId, "诊疗ID不能为空");
        Assert.notNull(doctorId, "医生ID不能为空");

        // 1. 调用Mapper查询详情
        TreatmentVo vo = baseMapper.selectDoctorTreatmentDetail(treatmentId, doctorId);
        if (vo == null) {
            return null;
        }

        // 2. 处理药品列表（如果有多个药品，这里通过单独查询补充，避免连表重复）
        TreatmentRecord record = getById(treatmentId);
        if (record != null && record.getDrugIds() != null) {
            try {
                // 解析drugIds（JSON数组）
                List<Integer> drugIds = objectMapper.readValue(
                        record.getDrugIds().toString(),
                        new TypeReference<List<Integer>>() {}
                );
                // 这里可单独查询药品表获取完整药品信息（优化：避免连表重复）
                // 简化版：直接使用连表查询的药品数据
            } catch (Exception e) {
                log.error("解析药品ID失败", e);
                vo.setDrugs(new ArrayList<>());
            }
        }

        return vo;
    }



}